# !encoding=utf-8

import os
import sys
import time
import json
import socket
import struct
import socketserver

from conf import modules
from socketserver import DatagramRequestHandler


class StickService(DatagramRequestHandler):
    car = None

    def __init__(self, request, client_address, server):
        super(StickService, self).__init__(request, client_address, server)

    def handle(self):
        data = self.rfile.read()
        begin = struct.unpack("c", data[:1])
        trigger_time = struct.unpack("i", data[1:5])[0]
        if time.time() - trigger_time >= 1: # 1s前的数据全部丢弃
            return

        btn_cnt = struct.unpack("B", data[5:6])[0]

        pos = 6
        btn_status = list()

        for i in range(btn_cnt):
            btn_type = struct.unpack("B", data[pos: pos + 1])[0]
            btn_idx = struct.unpack("B", data[pos + 1: pos + 2])[0]
            btn_val = struct.unpack("h", data[pos + 2: pos + 4])[0]
            pos += 4
            btn_status.append({"idx": btn_idx, "value": btn_val, "type": btn_type})

        # type: 1-按键，2-方向
        #print(btn_status)
        stick_btn_type = 1
        stick_axis_type = 2
        # 将手柄消息封装成json,发送到engine
        # 手柄可能会按下多个键，所以可能要发多次
        engine_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

        axis_action = None
        for btn in btn_status:
            btn_idx = btn["idx"]
            btn_type = btn["type"]
            btn_val = btn["value"]

            if btn_type == stick_btn_type:
                request = {"action": "", "term": "10"}
                if btn_val == 1:
                    if btn_idx == 1:
                        request["action"] = "turn-right-steer"
                    if btn_idx == 3:
                        request["action"] = "turn-left-steer"
                    if btn_idx == 4:
                        request["action"] = "flash-light"
                    if btn_idx == 11:
                        running = not running
                    engine_sock.sendto(json.dumps(request).encode(), ("127.0.0.1", 8000))
            elif btn_type == stick_axis_type:
                request = {"action": "stop", "term": "10"}
                if btn_val != 0:
                    if btn_idx == 6:
                        if btn_val < 0:
                            axis_action = "left"
                        elif btn_val > 0:
                            axis_action = "right"
                    if btn_idx == 7:
                        if btn_val < 0:
                            axis_action  = "forward"
                        elif btn_val > 0:
                            axis_action  = "backward"
        if axis_action is None:  # 没有按方向键
            request["action"] = "stop"
        else:
            request["action"] = axis_action
        engine_sock.sendto(json.dumps(request).encode(), ("127.0.0.1", 8000))

    @classmethod
    def run(cls, port):
        server = socketserver.ThreadingUDPServer(('127.0.0.1', port), StickService)
        server.serve_forever()


if __name__ == "__main__":
    port = int(sys.argv[1])
    StickService.run(port)
